package edu.xlh.travel.asynctask;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.xlh.travel.common.EchartInRedisConstant;
import edu.xlh.travel.dao.ForeHotelOrderDao;
import edu.xlh.travel.dao.HotelDao;
import edu.xlh.travel.dao.OrdersDao;
import edu.xlh.travel.enumeration.OrderStatusEnum;
import edu.xlh.travel.enumeration.OrderTypeEnum;
import edu.xlh.travel.pojo.Hotel_orders;
import edu.xlh.travel.pojo.Orders;
import edu.xlh.travel.service.ForeHotelOrderService;
import edu.xlh.travel.service.OnlineUserInfoService;
import edu.xlh.travel.service.OrdersService;
import edu.xlh.travel.service.UserService;
import edu.xlh.travel.util.CurrentWeekToNumber;
import edu.xlh.travel.echart.util.InitReportDataArrayInRedisUtil;
import edu.xlh.travel.redis.utils.JedisManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;


import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


@Component
public class AsyncTask {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private JedisManager jedisManager;
    @Autowired
    private OrdersDao ordersDao;
    @Autowired
    private UserService userService;
    @Autowired
    private OnlineUserInfoService onlineUserInfoService;
    @Autowired
    private InitReportDataArrayInRedisUtil initReportDataArrayInRedisUtil;

    private OrdersService ordersService;
    private ForeHotelOrderService foreHotelOrderService;

    @Autowired
    private ForeHotelOrderDao foreHotelOrderDao;

    @Lazy//解决AsyncTask和OrdersService循环依赖问题
    public AsyncTask(OrdersService ordersService , ForeHotelOrderService foreHotelOrderService) {
        this.ordersService = ordersService;
        this.foreHotelOrderService = foreHotelOrderService;
    }


    private static String writeKey = EchartInRedisConstant.ECHART_RD_DATA+"::"
            +EchartInRedisConstant.DATACOUNTWRITE_RD_LIST;
    private static String readKey = EchartInRedisConstant.ECHART_RD_DATA+"::"
            +EchartInRedisConstant.DATACOUNTREAD_RD_LIST;
    @Async
    public void doHandleExpiredOrder(String orderType) {
        while (true) {
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new StringRedisSerializer());
            ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
            Set<ZSetOperations.TypedTuple<String>> items = zSetOperations.rangeWithScores("orderId", 0, -1);
            if (items == null || items.isEmpty()) {
              /*  System.out.println("当前没有等待的任务");
                try {
                    Thread.sleep(30000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }*/
            } else {
                String orderId = ((ZSetOperations.TypedTuple<String>) items.toArray()[0]).getValue().toString();
               /* System.out.println(orderId1);*/
                double score = ((ZSetOperations.TypedTuple<String>) items.toArray()[0]).getScore();
               /* System.out.println(score);*/

                Calendar cal = Calendar.getInstance();
                int nowMinute = (int) cal.get(Calendar.MINUTE);
                //比对第一个，即过期时间最小的那个，这个都不过期，其他更不可能
                if (nowMinute >= score) {
                    //可使用延时双删或者canal感知mysql
                    if (orderType.equals(OrderTypeEnum.scenicOrder.getCode())) {
                        Orders orders = ordersDao.findById(orderId).get();
                        if (OrderStatusEnum.paying.getCode().equals(orders.getStatus())) {
                            System.out.println("订单取消时间: "+nowMinute);
                            System.out.println("订单score: "+score);
                            ordersDao.updateStatusByOrderId(OrderStatusEnum.endTrade.getCode(),orderId);
                            redisTemplate.opsForZSet().remove("orderId", orderId);
                            System.out.println("AsyncTask线程Id: "+Thread.currentThread().getId());
                        }
                    }else {
                        Hotel_orders hotel_orders = foreHotelOrderDao.findById(orderId).get();
                        if (OrderStatusEnum.paying.getCode().equals(hotel_orders.getStatus())) {
                            System.out.println("订单取消时间: "+nowMinute);
                            System.out.println("订单score: "+score);
                            foreHotelOrderDao.updateStatusByHotelOrderId(OrderStatusEnum.endTrade.getCode(),orderId);
                            redisTemplate.opsForZSet().remove("orderId", orderId);
                            System.out.println("AsyncTask线程Id: "+Thread.currentThread().getId());
                        }
                    }
                    //System.out.println(Thread.currentThread().getId() + "线程:"+ System.currentTimeMillis()/1000+"ms:redis消费了一个任务：消费的订单OrderId为" + orderId);
                }
            }
        }
    }

    //异步统计本周每天报表数据
    @Async
    public void doHandleWriteReportDataToRedis() {
        Integer userConut = userService.getUserCount();
        Integer orderConut = ordersService.getOrderCount();
        Integer onlineUserConut = onlineUserInfoService.getOnlineUserCount();
        Long index = Long.parseLong(CurrentWeekToNumber.transformWeekToString());
        Map<String, Integer> hashMap = new HashMap<String, Integer>();
        hashMap.put("用户数量" , userConut);
        hashMap.put("订单数量" , orderConut);
        hashMap.put("在线用户" , onlineUserConut);
        ObjectMapper mapper = new ObjectMapper();
        String dataStr = null;
        try {
            dataStr = mapper.writeValueAsString(hashMap);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        //项目刚上线
        if (!jedisManager.exists(writeKey)) {//TODO 待完善
            //初始化写数组
            initReportDataArrayInRedisUtil.getInitReportDataArrayOfWrite();
            //将上线时当天的数据写进write的k-v
            jedisManager.lset(writeKey , index , dataStr);
            System.out.println(index+"\t\t\t\t"+dataStr);
        } else if ("0".equals(index)){
            //每周一写入readKey，删除writeKey
                //1.删除上一周的readKey
                if(jedisManager.exists(readKey)) {
                    jedisManager.del(readKey);
                }
                //删除
                initReportDataArrayInRedisUtil.getInitReportDataArrayOfRead();
                for (long i = 0 ; i < 7 ; i++) {
                    //注意，要做判空处理
                    String writeValue = jedisManager.lindex(writeKey, i);
                    jedisManager.lset(readKey , i , writeValue);
                }
                //删除write的k-v
                jedisManager.del(writeKey);
                initReportDataArrayInRedisUtil.getInitReportDataArrayOfWrite();
                jedisManager.lset(writeKey , 0L , dataStr);

        } else {
            System.out.println(index+"\t\t\t\t"+dataStr);
            jedisManager.lset(writeKey  , index , dataStr);
        }
    }
}
